package com.power.sifa.approve.executor.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.aventrix.jnanoid.jnanoid.NanoIdUtils;
import com.plf.common.domain.ResponseDTO;
import com.plf.common.domain.YesNo;
import com.plf.common.utils.PdfConvertUtil;
import com.plf.common.utils.StringUtil;
import com.plf.common.utils.WordUtil;
import com.plf.core.base.model.Ha_attachment;
import com.plf.core.base.service.Ha_attachmentService;
import com.power.external.window.api.IWindowFeign;
import com.power.flowable.api.IPersonalFeign;
import com.power.sifa.approve.dao.Apl_limit_hearDao;
import com.power.sifa.approve.model.*;
import com.power.sifa.approve.model.enumeration.*;
import com.power.sifa.approve.service.*;
import com.power.sifa.approve.thread.ThreadPoolUtil;
import com.power.sifa.base.model.enumeration.Tp_noticemsg;
import com.power.sifa.net.service.ApplyService;
import com.power.sifa.util.executor.AbstractPostExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 决定完成服务
 */
@Component
@Slf4j
public class HearAuditDecision extends AbstractPostExecutor {

    // 用户id
    private String userid;
    // 环节分类标识
    private String category;
    // 用户名
    private String username;
    // 单位id
    private String sectionid;
    // 单位名称
    private String sectionname;
    // 部门id
    private String deptid;
    // 部门名称
    private String deptname;
    // 处理意见
    private String remark;
    // 行政区划
    private String adid;
    // 环节名称
    private String taskname;

    @Resource
    private Apl_admreviewService apl_admreviewService;
    @Resource
    private BusinessApproveService businessApproveService;
    @Resource
    private Apl_mainService apl_mainService;
    @Resource
    private IPersonalFeign iPersonalFeign;
    @Resource
    private Apl_limit_hearService apl_limit_hearService;
    @Resource
    private Apl_dossierService apl_dossierService;
    @Resource
    private Apl_archiveService apl_archiveService;
    @Resource
    private Apl_arrive_detailService apl_arrive_detailService;
    @Resource
    private Apl_limit_hearDao apl_limit_hearDao;
    @Resource
    private IWindowFeign iWindowFeign;

    @Resource
    private ApplyService applyService;

    @Resource
    private Apl_decision_recordService apl_decision_recordService;

    @Resource
    private Ha_attachmentService ha_attachmentService;

    @Resource
    private Aprv_process_materialsService aprv_process_materialsService;

    @Resource
    private Apl_decistiontypeService apl_decistiontypeService;


    @Override
    public void init(Map<String, Object> initdata) {
        this.userid = (String) initdata.get("userid");
        this.category = (String) initdata.get("category");
        this.username = (String) initdata.get("username");
        this.sectionid = (String) initdata.get("sectionid");
        this.sectionname = (String) initdata.get("sectionname");
        this.deptid = (String) initdata.get("deptid");
        this.deptname = (String) initdata.get("deptname");
        this.remark = (String) initdata.get("remark");
        this.adid = (String) initdata.get("adid");
        this.taskname = (String) initdata.get("taskname");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> execute() throws Exception {
        // 1. 生成和保存三级审批文书
        Apl_admre_audit auditObj = this.businessApproveService.createThreeLevelApprove(super.applyid, this.userid, this.username, Tp_proctype.HEAR_DECISION);
        Apl_main mainObj = this.apl_mainService.getById(super.applyid);
        Apl_main faMainObj = this.apl_mainService.getById(auditObj.getApplyid());

        // 1.1 生成干预行政复议活动记录表
        this.generateDecisionInterneFile(auditObj, mainObj.getFormid());
        // 2. 通过即结束
        // 2.1 清空所有子状态
        Apl_admreview admreObj = this.apl_admreviewService.getById(faMainObj.getId());
        if (null == auditObj.getDecisiontype()) {
            throw new RuntimeException("决定类型不能为空");
        }
        admreObj.setSonstatus(null);
        // 2.2 更新业务主表为已审理
        admreObj.setStatus(St_admreview.HEAR);
        // 2.3 更新决定时间
        Date decidate = new Date();
        String now = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(decidate);
        admreObj.setDecisiondate(now);

        // 查询决定流程变量
        {
            ResponseDTO res = iPersonalFeign.getProcessVariable(mainObj.getInstid());
            if (0 != res.getCode()) {
                log.error("HearAuditDecision 查询承办人和协办人流程变量失败 msg -> {}", res.getMsg());
                throw new RuntimeException("查询承办人和协办人流程变量失败");
            }
            Map<String, Object> variableMap = (Map<String, Object>) res.getData();
            Integer decisiontype = (Integer) variableMap.get("decisiontype");
            Integer decisiontypeid = (Integer) variableMap.get("decisiontypeid");
            String decisiontypename = (String) variableMap.get("decisiontypename");
            if (StringUtil.isEmpty(decisiontypeid) || StringUtil.isEmpty(decisiontypename)) {
                log.error("HearAuditDecision 流程业务变量缺失 -> {}, {}", decisiontypeid, decisiontypename);
                throw new RuntimeException("流程业务变量缺失");
            }
            admreObj.setDecisiontype(decisiontype);
            admreObj.setDecisiontypeid(decisiontypeid);
            admreObj.setDecisiontypename(decisiontypename);
            this.apl_admreviewService.saveOrUpdate(admreObj);
            // 2.4 更新办结时限的决定日期
            this.apl_limit_hearDao.updateDecidate(faMainObj.getId(), decidate);
        }

        // 2.5 关闭所有在办子流程
        ResponseDTO res = this.iPersonalFeign.terminationSonProcess(faMainObj.getInstid(), mainObj.getInstid(), this.userid, "申请已决定，故中途办结");
        if (0 != res.getCode()) {
            log.error("HearAuditDecision 关闭所有在办子流程失败 ->  msg[{}]", res.getMsg());
            throw new RuntimeException("关闭所有在办子流程失败");
        }

        // 3. 获取需要修改业务状态的实例id
        List<String> instids = (List<String>) res.getData();
        if (!CollectionUtils.isEmpty(instids)) {
            this.apl_mainService.updateStatusByInstid(St_apply.FINISH, instids);
        }

        // 4. 审理时限记录, 添加决定日期
        Apl_limit_hear hearObj = this.apl_limit_hearService.getById(auditObj.getApplyid());
        if (null == hearObj) {
            log.error("HearAuditDecision 未找到审理时限记录");
            throw new RuntimeException("未找到审理时限记录");
        }
        // 状态改为已结束
        this.apl_mainService.updateStatus(faMainObj.getId(), St_apply.FINISH);

        // 5先激活 (没挂起就拿一个taskid)
        ResponseDTO activeRes = this.iPersonalFeign.activationProcess(faMainObj.getInstid());
        if (0 != activeRes.getCode()) {
            log.error("HearAuditDecision 激活父流程失败 -> msg[{}]", activeRes.getMsg());
            throw new RuntimeException("HearAuditDecision 激活父流程失败 -> " + activeRes.getMsg());
        }
        // 5.1 父流程自动走一步
        String taskid = (String) activeRes.getData(); // 父流程任务id
        ThreadPoolUtil.executor.execute(() -> {
            ResponseDTO axecRes = this.iPersonalFeign.processNext(faMainObj.getFormid(), faMainObj.getId(), taskid, userid, new HashMap());
            if (0 != axecRes.getCode()) {
                log.error("HearAuditDecision 完成父流程任务失败 -> msg[{}]", axecRes.getMsg());
                throw new RuntimeException("HearAuditDecision 完成父流程任务失败");
            }
        });


        // 6. 初始归档数据
        ThreadPoolUtil.executor.execute(() -> {
            // 6.1 初始化归档首页数据
            this.apl_archiveService.initialArchiveData(faMainObj.getId());
            // 6.2 初始化归档电子卷宗数据
            this.apl_dossierService.buildInitDossier(faMainObj.getId());
        });


        // 刷新文书日期
        this.businessApproveService.processEndedUpdatePreviewDoc(auditObj.getApplyid(), Tp_proctype.HEAR_DECISION, admreObj.getDecisiontype());
        // 文书盖章
        this.businessApproveService.templateStamp(auditObj.getApplyid(), Tp_proctype.HEAR_DECISION);

        // 创建送达通知
        if (ObjectUtil.isNotNull(admreObj.getDecisiontype())) {
            Integer decisiontype = admreObj.getDecisiontype();
            Integer decisiontypeid = admreObj.getDecisiontypeid();
            Apl_decistiontype apl_decistiontype = apl_decistiontypeService.getById(decisiontypeid);
            Integer decisionMaterial = ObjectUtil.isNotEmpty(apl_decistiontype) ? apl_decistiontype.getMaterialtype() : Tp_procmaterial.HEAR_DECISION;
            if (decisiontype.equals(Tp_decision.TERMEDIATE)) {
                this.apl_arrive_detailService.createSaveNotice(faMainObj.getId(), faMainObj.getAcceptcode(), userid,
                        7, faMainObj.getAcceptcode() + "已审批通过，请及时送达《行政复议调解书》", decisionMaterial, Tp_noticemsg.ADMREIVEW_ARRIVE);
            } else {
                this.apl_arrive_detailService.createSaveNotice(faMainObj.getId(), faMainObj.getAcceptcode(), userid,
                        7, faMainObj.getAcceptcode() + "已审批通过，请及时送达《行政复议决定书》", decisionMaterial, Tp_noticemsg.ADMREIVEW_ARRIVE);
            }
        }

        Map<String, Object> params = new HashMap<>(16);
        params.put("isAeliver", true);
        return params;
    }


    private void generateDecisionInterneFile(Apl_admre_audit auditObj, String formid) throws Exception {

        SimpleDateFormat formatT = new SimpleDateFormat("yyyy年M月d日");
        Map<String, Object> formData = this.applyService.formLoadField(formid, super.applyid);
        // 查询决定的干预行政复议活动记录数据
        List<Apl_decision_record> recordList = apl_decision_recordService.getDecisionRecords(auditObj.getApplyid(), auditObj.getId());
        // 2. 生成并上传文件
        Ha_attachment attachment;
        byte[] pdfByte;
        OutputStream os = null;
        InputStream is = null;
        try {
            // 主办人
            Apl_decision_record mainRecord = recordList.stream().filter(el -> el.getSigntype().equals(YesNo.YES)).findAny().orElse(null);
            // 协办人
            Apl_decision_record subRecord = recordList.stream().filter(el -> el.getSigntype().equals(YesNo.NO)).findAny().orElse(null);

            formData.put("m_1", "☑");
            formData.put("m_2_1", "□");
            formData.put("m_2_2", "□");
            formData.put("m_2_3", "□");
            formData.put("m_2_4", "□");
            formData.put("m_other_1", "");
            formData.put("m_3_1", "□");
            formData.put("m_3_2", "□");
            formData.put("m_3_3", "□");
            formData.put("m_3_4", "□");
            formData.put("m_other_2", "");
            formData.put("m_detail", "");
            formData.put("m_sign", "");
            formData.put("m_signdate", "");

            if (ObjectUtil.isNotNull(mainRecord)) {
                // 设置默认值
                // 无此类情况
                if (mainRecord.getIsexist().equals(YesNo.YES)) {
                    // 有此类情况
                    formData.put("m_1", "□");
                    String personradio = mainRecord.getPersonradio();
                    List<String> personList = Arrays.asList(personradio.split(","));
                    if (CollectionUtil.isNotEmpty(personList)) {
                        personList.stream().forEach(el -> {
                            if (Integer.valueOf(el).equals(Tp_intervene_person.SELF)) {
                                formData.put("m_2_1", "☑");
                            } else if (Integer.valueOf(el).equals(Tp_intervene_person.WORK)) {
                                formData.put("m_2_2", "☑");
                            } else if (Integer.valueOf(el).equals(Tp_intervene_person.LAW)) {
                                formData.put("m_2_3", "☑");
                            } else if (Integer.valueOf(el).equals(Tp_intervene_person.OTHER)) {
                                formData.put("m_2_4", "☑");
                                formData.put("m_other_1", mainRecord.getPersonother());
                            }
                        });
                    }

                    String contentradio = mainRecord.getContentradio();
                    List<String> contentList = Arrays.asList(contentradio.split(","));
                    if (CollectionUtil.isNotEmpty(contentList)) {
                        personList.stream().forEach(el -> {
                            if (Integer.valueOf(el).equals(Tp_intervene_content.DELEGATE)) {
                                formData.put("m_3_1", "☑");
                            } else if (Integer.valueOf(el).equals(Tp_intervene_content.PROGRAM)) {
                                formData.put("m_3_2", "☑");
                            } else if (Integer.valueOf(el).equals(Tp_intervene_content.RESULT)) {
                                formData.put("m_3_3", "☑");
                            } else if (Integer.valueOf(el).equals(Tp_intervene_content.OTHER)) {
                                formData.put("m_3_4", "☑");
                                formData.put("m_other_2", mainRecord.getContentother());
                            }
                        });
                    }
                }
                formData.put("m_detail", mainRecord.getDetail());
                formData.put("m_sign", mainRecord.getSign());
                formData.put("m_signdate", formatT.format(mainRecord.getSigndate()));
            }

            formData.put("s_1", "☑");
            formData.put("s_2_1", "□");
            formData.put("s_2_2", "□");
            formData.put("s_2_3", "□");
            formData.put("s_2_4", "□");
            formData.put("s_other_1", "");
            formData.put("s_3_1", "□");
            formData.put("s_3_2", "□");
            formData.put("s_3_3", "□");
            formData.put("s_3_4", "□");
            formData.put("s_other_2", "");
            formData.put("s_detail", "");
            formData.put("s_sign", "");
            formData.put("s_signdate", "");

            if (ObjectUtil.isNotNull(subRecord)) {
                if (subRecord.getIsexist().equals(YesNo.YES)) {
                    // 有此类情况
                    formData.put("s_1", "□");
                    String personradio = subRecord.getPersonradio();
                    List<String> personList = Arrays.asList(personradio.split(","));
                    if (CollectionUtil.isNotEmpty(personList)) {
                        personList.stream().forEach(el -> {
                            if (Integer.valueOf(el).equals(Tp_intervene_person.SELF)) {
                                formData.put("s_2_1", "☑");
                            } else if (Integer.valueOf(el).equals(Tp_intervene_person.WORK)) {
                                formData.put("s_2_2", "☑");
                            } else if (Integer.valueOf(el).equals(Tp_intervene_person.LAW)) {
                                formData.put("s_2_3", "☑");
                            } else if (Integer.valueOf(el).equals(Tp_intervene_person.OTHER)) {
                                formData.put("s_2_4", "☑");
                                formData.put("s_other_1", subRecord.getPersonother());
                            }
                        });
                    }

                    String contentradio = subRecord.getContentradio();
                    List<String> contentList = Arrays.asList(contentradio.split(","));
                    if (CollectionUtil.isNotEmpty(contentList)) {
                        personList.stream().forEach(el -> {
                            if (Integer.valueOf(el).equals(Tp_intervene_content.DELEGATE)) {
                                formData.put("s_3_1", "☑");
                            } else if (Integer.valueOf(el).equals(Tp_intervene_content.PROGRAM)) {
                                formData.put("s_3_2", "☑");
                            } else if (Integer.valueOf(el).equals(Tp_intervene_content.RESULT)) {
                                formData.put("s_3_3", "☑");
                            } else if (Integer.valueOf(el).equals(Tp_intervene_content.OTHER)) {
                                formData.put("s_3_4", "☑");
                                formData.put("s_other_2", subRecord.getContentother());
                            }
                        });
                    }
                }
                formData.put("s_detail", subRecord.getDetail());
                formData.put("s_sign", subRecord.getSign());
                formData.put("s_signdate", formatT.format(subRecord.getSigndate()));
            }

            WordUtil wordUtil = new WordUtil("HearDecisionRecord.docx");
            wordUtil.replaceTable(formData);
            os = wordUtil.createWord();
            is = new ByteArrayInputStream(((ByteArrayOutputStream) os).toByteArray());
            pdfByte = PdfConvertUtil.word2pdfWithFont(is);
            attachment = ha_attachmentService.upload(new ByteArrayInputStream(pdfByte), "干预行政复议活动记录表.pdf");
            log.info("generateDecisionInterneFile 干预行政复议活动记录表生成并保存成功 -> {}", attachment.getId());
        } catch (Exception e) {
            e.printStackTrace();
            log.error("generateDecisionInterneFile 干预行政复议活动记录表生成并保存失败 ->  msg[{}]", e.getMessage());
            throw new RuntimeException("generateThreeLevelApprove 干预行政复议活动记录表生成并保存失败 -> " + e.getMessage());
        } finally {
            if (os != null) {
                os.close();
            }
            if (is != null) {
                is.close();
            }
        }

        // 2. 保存审批系统文书, 只存父流程
        Aprv_process_materials docObj = new Aprv_process_materials(Tp_procmaterialEnum.HEAR_INTERVENE);
        docObj.setId(auditObj.getApplyid() + NanoIdUtils.randomNanoId());
        // 通知书类型枚举
        docObj.setMattype(Tp_procmaterial.HEAR_INTERVENE);
        docObj.setAttachid(attachment.getId());
        docObj.setCreateuserid(userid);
        docObj.setCreateuser(username);
        docObj.setCreatetime(new Date());
        docObj.setApplyid(auditObj.getApplyid());
        docObj.setType(Tp_proctype.HEAR_DECISION);
        docObj.setSonapplyid(auditObj.getId());
        this.aprv_process_materialsService.saveOrUpdate(docObj);
    }


}
